//
//  DCDownloadOpration.m
//  DCDownloadOpration
//
//  Created by collegepre on 16/4/1.
//  Copyright © 2016年 Wade. All rights reserved.
//

#import "DCDownloadOpration.h"
#import "DCDownloadConst.h"
#import "NSString+DCDownload.h"

@interface DCDownloadOpration()
{
    DCDownloadState _state;
    NSInteger _totalBytesWritten;
}
/** 任务 */
@property (strong, nonatomic) NSURLSessionDataTask *task;
/** 文件流 */
@property (strong, nonatomic) NSOutputStream *stream;

/** 已下载的数量 */
@property (assign, nonatomic) NSInteger totalBytesWritten;
/** 文件的总大小 */
@property (assign, nonatomic) NSInteger totalBytesExpectedToWrite;

@property (nonatomic, strong) NSError *error;

@end

@implementation DCDownloadOpration

#pragma 懒加载

- (NSOutputStream *)stream
{
    if (_stream == nil) {
        _stream = [NSOutputStream outputStreamToFileAtPath:self.destinationPath append:YES];
    }
    return _stream;
}

- (NSInteger)totalBytesWritten
{
    return self.destinationPath.fileSize;
}

- (NSInteger)totalBytesExpectedToWrite
{
    if (!_totalBytesExpectedToWrite) {
        _totalBytesExpectedToWrite = [_totalFileSizes[self.url] integerValue];
    }
    return _totalBytesExpectedToWrite;
}


#pragma mark - 状态控制
- (void)setState:(DCDownloadState)state
{
    DCDownloadState oldState = self.state;
    if (state == oldState) return;
    
    _state = state;
    
    // 发通知
    [self notifyStateChange];
}


/**
 *  初始化任务
 */
- (void)setupTask:(NSURLSession *)session
{
    if (self.task) return;
    
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.url]];
    
    NSString *range = [NSString stringWithFormat:@"bytes=%zd-", self.totalBytesWritten];
    [request setValue:range forHTTPHeaderField:@"Range"];
    
    self.task = [session dataTaskWithRequest:request];
    // 设置描述
    self.task.taskDescription = self.url;
}

/**
 *  通知进度改变
 */
- (void)notifyProgressChange
{
    if(self.downloadResumingBlock)
    {
        self.downloadResumingBlock(self.totalBytesWritten, self.totalBytesExpectedToWrite,self);
    }
    [DCDownloadNoteCenter postNotificationName:DCDownloadProgressDidChangeNotification
                                        object:self
                                      userInfo:@{DCDownloadInfoKey : self}];
}

/**
 *  通知下载完毕
 */
- (void)notifyStateChange
{
    
    // 如果
    if (self.downloadStateChangeBlock) {
        
        self.downloadStateChangeBlock(self.state, self.destinationPath, self.error,self);
        
        [DCDownloadNoteCenter postNotificationName:DCDownloadStateDidChangeNotification
                                            object:self
                                          userInfo:@{DCDownloadInfoKey : self}];
    }
}

/**
 *  取消
 */
- (void)cancel
{
    if (self.state == DCDownloadStateCompleted || self.state == DCDownloadStateNone) return;
    
    [self.task cancel];
    _state = DCDownloadStateNone;
}


/**
 *  恢复
 */
- (void)resume
{
//    if (self.state == DCDownloadStateCompleted || self.state == DCDownloadStateResumed) return;
    
    [self.task resume];
    self.state = DCDownloadStateResumed;
}

/**
 * 等待下载
 */
- (void)willResume
{
//    if (self.state == DCDownloadStateCompleted || self.state == DCDownloadStateWaiting) return;
    
    self.state = DCDownloadStateWaiting;
}

/**
 *  暂停
 */
- (void)suspend
{
    if (self.state == DCDownloadStateCompleted || self.state == DCDownloadStateSuspened) return;
    
    if (self.state == DCDownloadStateResumed) { // 如果是正在下载
        [self.task suspend];
        self.state = DCDownloadStateSuspened;
    } else { // 如果是等待下载
        self.state = DCDownloadStateNone;
    }
}

#pragma mark - 代理方法处理
- (void)didReceiveResponse:(NSHTTPURLResponse *)response
{
    // 获得文件总长度
    if (!self.totalBytesExpectedToWrite) {
        self.totalBytesExpectedToWrite = [response.allHeaderFields[@"Content-Length"] integerValue] + self.totalBytesWritten;
        // 存储文件总长度
        _totalFileSizes[self.url] = @(self.totalBytesExpectedToWrite);
        [_totalFileSizes writeToFile:[self.destinationPath stringByDeletingLastPathComponent] atomically:YES];
    }
    
    // 打开流
    [self.stream open];
    
    // 清空错误
    self.error = nil;
}

- (void)didReceiveData:(NSData *)data
{
    // 写数据
    NSInteger result = [self.stream write:data.bytes maxLength:data.length];
    if (result == -1) {
        self.error = self.stream.streamError;
        [self.task cancel]; // 取消请求
    }else{
        [self notifyProgressChange]; // 通知进度改变
    }
}

- (void)didCompleteWithError:(NSError *)error
{
    // 关闭流
    [self.stream close];
    self.stream = nil;
    self.task = nil;
    
    // 错误(避免nil的error覆盖掉之前设置的self.error)
    self.error = error ? error : self.error;
    // 设置状态
    self.state = error ? DCDownloadStateFail : DCDownloadStateCompleted;
   
    [self notifyStateChange];
}

@end
